package com.nowcoder.community.quartz;

import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.service.DiscussPostService;
import com.nowcoder.community.service.ElasticSearchService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.RedisKeyUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class PostScoreRefreshJob implements Job, CommunityConstant {

    private static final Logger logger = LoggerFactory.getLogger(PostScoreRefreshJob.class);

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private RedisTemplate redisTemplate;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private DiscussPostService discussPostService;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private LikeService likeService;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private ElasticSearchService elasticSearchService;

    // 牛客网成立日期
    private static final Date epoch;

    static {
        try {
            epoch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-08-01 00:00:00");
        } catch (ParseException e) {
            throw new RuntimeException("初始化牛客纪元失败", e);
        }
    }

    private void refresh(int discussPostId) {
        DiscussPost post = discussPostService.findDiscussPostById(discussPostId);
        if(post == null) {
            logger.error("该帖子不存在: id = " + discussPostId);
        }
        else {
            boolean wonderful = post.getStatus() == 1;
            int commentCount = post.getCommentCount();
            long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId);

            // 计算权重
            double weight = (double) (wonderful ? 75 : 0) + commentCount * 10 + likeCount * 2;
            // 日期差值
            double dayDiff = (post.getCreateTime().getTime() - epoch.getTime()) / (1000 * 3600 * 24);

            double score = Math.max(Math.log10(weight), 0) + dayDiff;

            discussPostService.updateScoreById(discussPostId, score);

            // 同步ElasticSearch引擎
            post.setScore(score);
            elasticSearchService.saveDiscussPost(post);
        }
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String redisKey = RedisKeyUtil.getPostScoreKey();
        BoundSetOperations operations = redisTemplate.boundSetOps(redisKey);
        if(operations.size() == 0) {
            logger.info("[任务取消] 帖子排行榜不需要刷新!");
            return;
        }
        logger.info("[任务开始] 正在刷新帖子排行榜" + operations.size());
        while(operations.size() > 0) {
            // 注意此处要做弹出操作
            // 避免redis缓存越来越满
            Object obj = operations.pop();
            // 为了避免一些奇奇怪怪的bug
            // 对reids中弹出的数据做类型判断
            // 并统一转化成int类型
            if(obj instanceof Integer) {
                this.refresh((int) obj);
            }
            if(obj instanceof String) {
                this.refresh(Integer.parseInt((String) obj));
            }
        }
        logger.info("[任务结束] 帖子排行榜刷新完毕");
    }
}
